home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / mklfs / RCS / mklfs.c,v < prev    next >
Encoding:
Text File  |  1992-12-04  |  46.4 KB  |  1,576 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    jhh:1.5; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     92.12.03.17.09.13;  author shirriff;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     92.06.19.20.07.37;  author jhh;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     91.12.17.22.14.21;  author jhh;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     91.12.17.15.04.21;  author mendel;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     91.05.31.11.09.07;  author mendel;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @Program to make lfs file system on disk.
  37. @
  38.  
  39.  
  40. 1.5
  41. log
  42. @Added sanity checking.
  43. @
  44. text
  45. @/* 
  46.  * mklfs.c --
  47.  *
  48.  *    The mklfs program - Make a LFS file system on a disk.
  49.  *
  50.  * Copyright 1989 Regents of the University of California
  51.  * Permission to use, copy, modify, and distribute this
  52.  * software and its documentation for any purpose and without
  53.  * fee is hereby granted, provided that the above copyright
  54.  * notice appear in all copies.  The University of California
  55.  * makes no representations about the suitability of this
  56.  * software for any purpose.  It is provided "as is" without
  57.  * express or implied warranty.
  58.  */
  59.  
  60. #ifndef lint
  61. static char rcsid[] = "$Header: /sprite/src/admin/mklfs/RCS/mklfs.c,v 1.4 92/06/19 20:07:37 jhh Exp Locker: shirriff $ SPRITE (Berkeley)";
  62. #endif /* not lint */
  63.  
  64. #ifdef __STDC__
  65. /*
  66.  * If we are compiling on a machine that has a ASCII C compiler, set the
  67.  * define _HAS_PROTOTYPES which causes the Sprite header files to 
  68.  * expand function definitions to included prototypes.
  69.  */
  70. #define    _HAS_PROTOTYPES 
  71. #endif /* __STDC__ */
  72.  
  73. #include <sprite.h>
  74. #include <varargs.h>
  75. #include <stdio.h>
  76. #include <cfuncproto.h>
  77.  
  78. #include <option.h>
  79. #include <stddef.h>
  80. #include <stdlib.h>
  81. #include <time.h>
  82. #include <unistd.h>
  83. #include <string.h>
  84. #include <sys/file.h>
  85. #include <sys/types.h>
  86. #include <sys/stat.h>
  87. #include <sys/time.h>
  88. #include <bstring.h>
  89.  
  90. #include <fs.h>
  91. #include <kernel/fs.h>
  92. #include <kernel/dev.h>
  93. #include <kernel/fsdm.h>
  94. #include <kernel/fslcl.h>
  95. #include <kernel/devDiskLabel.h>
  96.  
  97. #include <kernel/lfsDesc.h>
  98. #include <kernel/lfsDescMap.h>
  99. #include <kernel/lfsFileLayout.h>
  100. #include <kernel/lfsSegLayout.h>
  101. #include <kernel/lfsStableMem.h>
  102. #include <kernel/lfsSuperBlock.h>
  103. #include <kernel/lfsUsageArray.h>
  104. #include <kernel/lfsStats.h>
  105.  
  106. #include "getMachineInfo.h"
  107.  
  108. /*
  109.  * Mklfs works by building parts of the file system in memory and
  110.  * then writing the parts to disk.  The following data structures
  111.  * describe the in memory format on a segment and checkpoint region.
  112.  */
  113.  
  114. /*
  115.  * SegMem - Description of a segment being initialized for a new file system.
  116.  */
  117. typedef struct SegMem {
  118.     char    *startPtr;       /* Start of segment memory. */
  119.     unsigned int diskAddress;      /* Disk address of start of segment. */
  120.     char    *dataPtr;      /* Next data block to be allocated. */
  121.     int        activeBytes;      /* Number of active bytes in segment. */
  122.     char    *summaryPtr;      /* Next summary bytes to be allocated. */
  123. } SegMem;
  124.  
  125. /*
  126.  * CheckPointMem - Desciption of checkpoint region being initialized for
  127.  *           a new file system. 
  128.  */
  129. typedef struct CheckPointMem {
  130.     char    *startPtr;    /* Start of checkpoint memory. */
  131.     char    *memPtr;     /* Next checkpoint byte to be allocated. */
  132. } CheckPointMem;
  133.  
  134. /*
  135.  * In memory version of a Lfs Stable Memory data structure.
  136.  */
  137.  
  138. typedef struct StableMem {
  139.     LfsStableMemParams *paramsPtr;
  140.     char        **blockPtrs;
  141. } StableMem;
  142.  
  143. /*
  144.  * Attributes of the root directory of the new file system.
  145.  */
  146. typedef struct RootDir {
  147.     int truncVersion;    /* Truncate version number of root directory. */
  148.     int    accessTime;    /* Time of last access of root directory. */
  149.     int    numBlocks;    /* Number of blocks in root direcotry. */
  150.     int descBlockAddress; /* Disk address of root directory block. */
  151. } RootDir;
  152.  
  153. static RootDir root;
  154.  
  155. /*
  156.  * DEFAULT_SEG_SIZE - Default size of an LFS segment in bytes.
  157.  */
  158. #define    DEFAULT_SEG_SIZE (DEV_BYTES_PER_SECTOR*1024)
  159.  
  160. int    blockSize = DEV_BYTES_PER_SECTOR; /* Minumin unit of allocation for
  161.                        * the file system.  Must be at
  162.                        * least a sector size. 
  163.                        */
  164. int    segmentSize = DEFAULT_SEG_SIZE;      /* Size of LFS segment in bytes. */
  165. int    numberSegments = -1;          /* Number of sections occupied by
  166.                        * by the file system. -1 means 
  167.                        * compute based on disk size. 
  168.                        */
  169. int    descBlockSize = FS_BLOCK_SIZE;      /* Size of the descriptor blocks. */
  170. int    maxDesc      = -1;              /* Maximum number of descriptors to
  171.                        * support.  -1 means compute based
  172.                        * on disk size. 
  173.                        */
  174. int    usageArrayBlockSize = FS_BLOCK_SIZE;   /* Block size of usage array
  175.                         * Data structure. */
  176. int    descMapBlockSize = FS_BLOCK_SIZE;    /* Block size of desc map
  177.                          * data structure. */
  178. int    segAlignment = DEV_BYTES_PER_SECTOR; /* Address multiple to 
  179.                           * start segments. */
  180. int    maxNumCacheBlocks = -1;        /* Maximum number of file cache
  181.                      * blocks on the machine 
  182.                      * being used. */
  183. int    maxCacheBlocksCleaned = -1;    /* Maximum number of file cache
  184.                      * blocks used during cleaning.
  185.                      */
  186. Boolean    verbose = FALSE;
  187. int    serverID = -1;    /* Server ID to put in file system. */
  188. char    *deviceName;    /* Device to write file system to. */
  189. double  maxUtilization = .85; /* Maximum utilization allowed for file system. */
  190. double  segFullLevel = .95;   /* Minumum utilization of a full segment. */
  191. int    checkpointInterval = 60; /* Checkpoint every 60 seconds. */
  192. char    *prefix = "test";
  193. #if 0
  194. char    *prefix = "(new domain)";    /* File system name (prefix). */
  195. #endif
  196.  
  197. Option optionArray[] = {
  198.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  199. "This program generates an empty LFS file system. WARNING: This command\n will overwrite any existing data or file system on the specified device.\n Synopsis: \"mklfs [switches] deviceName [prefix]\"\n Command-line switches are:"},
  200.     {OPT_INT, "maxNumCacheBlocks", (Address) &maxNumCacheBlocks,
  201.         "Maximum number of cache blocks to avail on machine."},
  202.     {OPT_INT, "maxCacheBlocksCleaned", (Address) &maxCacheBlocksCleaned,
  203.         "Maximum number of cache blocks to clean at a time."},
  204.     {OPT_INT, "spriteID", (Address) &serverID,
  205.         "Sprite ID for superblock."},
  206.     {OPT_FLOAT, "maxUtilization", (Address) &maxUtilization,
  207.         "Maximum disk utilization allowed."},
  208.     {OPT_FLOAT, "segFullLevel", (Address) &segFullLevel,
  209.         "Minimum segment utilization for a full segment."},
  210.     {OPT_INT, "maxDesc", (Address) &maxDesc, 
  211.     "Maximum number of descriptors."},
  212.     {OPT_INT, "checkpointInterval", (Address) &checkpointInterval,
  213.     "Frequent of checkpoint in seconds."},
  214.     {OPT_INT, "blockSize", (Address) &blockSize, 
  215.     "Block size of file system in bytes."},
  216.     {OPT_INT, "segmentSize", (Address) &segmentSize, 
  217.     "Segment size of file system in bytes."},
  218.     {OPT_INT, "numSegments", (Address) &numberSegments, 
  219.     "Number of segment in file system."},
  220.     {OPT_INT, "segAlignment", (Address) &segAlignment,
  221.         "Insure that the first segment starts at this multiple."},
  222.     {OPT_INT, "descBlockSize", (Address) &descBlockSize, 
  223.     "Descriptor block size."},
  224.     {OPT_INT, "descMapBlockSize", (Address) &descMapBlockSize,
  225.         "Descriptor map block size"},
  226.     {OPT_INT, "usageArrayBlockSize", (Address) &usageArrayBlockSize,
  227.         "Segment usage array block size"},
  228.     {OPT_TRUE, "verbose", (Address)&verbose, "Print verbose information"}
  229. };
  230. /*
  231.  * Forward routine declartions. 
  232.  */
  233. extern void BuildInitialFileLayout _ARGS_((LfsFileLayoutParams *fileLayoutPtr,
  234.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  235. extern void BuildInitialDescMap _ARGS_((LfsDescMapParams *descParamsPtr, 
  236.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  237. extern void BuildInitialUsageArray _ARGS_((LfsSegUsageParams *usagePtr,
  238.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  239. static StableMem *BuildStableMem _ARGS_((int memType, int memBlockSize,
  240.             int entrySize, int maxNumEntries, 
  241.             LfsStableMemParams *smemParamsPtr));
  242. static void UpdateStableMem _ARGS_((StableMem *stableMemPtr, 
  243.             int entryNumber, char *entryPtr));
  244. static void LayoutStableMem _ARGS_((StableMem *stableMemPtr, 
  245.             SegMem *segPtr, CheckPointMem    *checkpointPtr));
  246.  
  247. static unsigned int GetDiskAddressOf _ARGS_((SegMem *segPtr));
  248. static void MakeRootDir _ARGS_((LfsFileDescriptor *rootDescPtr, 
  249.             LfsFileDescriptor *lostDescPtr,
  250.             SegMem *segPtr, RootDir *rootPtr));
  251. static void FileDescInit _ARGS_((LfsFileDescriptor *fileDescPtr, 
  252.             int fileNumber, int fileType));
  253. static void SetDescriptorMap _ARGS_((StableMem *stableMemPtr, 
  254.             int fileNumber, unsigned int diskAddress, 
  255.             int truncVersion, int accessTime));
  256. extern void WriteDisk _ARGS_((int diskFd, int blockOffset, char *bufferPtr, 
  257.             int bufferSize));
  258.  
  259. static Boolean IsPowerOfTwo _ARGS_((int ival));
  260. static Boolean IsMultipleOf _ARGS_((int imultiple, int ival));
  261. static int BlockCount _ARGS_((int objectSize, int blockSize));
  262. static void EraseOldFileSystem _ARGS_((int diskFd));
  263. static int ComputeDiskSize _ARGS_((int diskFd));
  264.  
  265. extern void panic();
  266. extern int  open _ARGS_((char *path, int flags, int mode));
  267.  
  268. /*
  269.  *----------------------------------------------------------------------
  270.  *
  271.  * main --
  272.  *
  273.  *    Main routine of mklfs - parse arguments and do the work.
  274.  *
  275.  * Results:
  276.  *    None.
  277.  *
  278.  * Side effects:
  279.  *    None.
  280.  *
  281.  *----------------------------------------------------------------------
  282.  */
  283.  
  284. int
  285. main(argc,argv)
  286.     int    argc;
  287.     char *argv[];
  288. {
  289.     int       diskFd, maxCheckPointSize, maxCheckPointBlocks, moduleType;
  290.     int        blocksPerSeg, segNum, startOffset;
  291.     LfsSuperBlock    *superBlockPtr;
  292.     char        *segMemPtr, *checkPointPtr, *summaryPtr;
  293.     SegMem    seg;
  294.     CheckPointMem checkpoint;
  295.     LfsSegSummaryHdr    *sumHdrPtr;
  296.     LfsCheckPointRegion *regionPtr;
  297.     LfsSegSummary     *segSumPtr;
  298.     LfsCheckPointHdr    *cpHdrPtr, *oldCheckPointPtr;
  299.     int        sizeInSectors;
  300.     extern ReturnStatus Proc_GetHostIDs 
  301.             _ARGS_((int *virtualHostPtr, int *physicalHostPtr));
  302.     int            partition;
  303.     struct timeval    tod;
  304.     struct stat        sbuf;
  305.  
  306.     GetMachineInfo(&serverID, &maxNumCacheBlocks);
  307.     /*
  308.      * Set the default number of file cache blocks to use while cleaning
  309.      * segments. We choose 8 megabytes or one third the number of cache
  310.      * blocks, which ever is less.
  311.      */
  312.  
  313.     if (maxCacheBlocksCleaned < 0) {
  314.     maxCacheBlocksCleaned = (8*1024*1024)/FS_BLOCK_SIZE;
  315.     if (maxCacheBlocksCleaned < maxNumCacheBlocks/3) {
  316.         maxCacheBlocksCleaned = maxNumCacheBlocks/3;
  317.     }
  318.     }
  319.  
  320.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  321.     if ((argc != 2) && (argc != 3)) { 
  322.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  323.      exit(1);
  324.     }
  325.     deviceName = argv[1];
  326.     if (argc == 3) {
  327.     prefix = argv[2];
  328.     if (strlen(prefix) >= 64) {
  329.         fprintf(stderr, "Length of prefix exceeds maximum (64)\n");
  330.         exit(1);
  331.     }
  332.     }
  333.     /*
  334.      * Validate the parameters.
  335.      */
  336.     if (!IsPowerOfTwo(blockSize) || (blockSize % DEV_BYTES_PER_SECTOR)) {
  337.     fprintf(stderr,"Blocksize (%d) not power of two or not multiple of sector size %d.\n",
  338.             blockSize, DEV_BYTES_PER_SECTOR);
  339.     exit(1);
  340.     }
  341.     if (!IsMultipleOf(segmentSize, blockSize)) {
  342.     fprintf(stderr,"Segment size (%d) is not a multiple of blockSize.\n",
  343.         segmentSize);
  344.     exit(1);
  345.     }
  346.     if (!IsMultipleOf(descBlockSize, blockSize)) {
  347.     fprintf(stderr,
  348.         "Descriptor block size (%d) is not a multiple of blockSize.\n",
  349.         descBlockSize);
  350.     exit(1);
  351.     }
  352.     if (!IsMultipleOf(descMapBlockSize, blockSize)) {
  353.     fprintf(stderr,
  354.         "Descriptor map block size (%d) is not a multiple of the blockSize.\n",
  355.         descMapBlockSize);
  356.     exit(1);
  357.     }
  358.     if (!IsMultipleOf(usageArrayBlockSize, blockSize)) {
  359.     fprintf(stderr,
  360.         "Usage array block size (%d) is not a multiple of the blockSize.\n",
  361.         usageArrayBlockSize);
  362.     exit(1);
  363.     }
  364.     if (!IsMultipleOf(segAlignment, DEV_BYTES_PER_SECTOR)) {
  365.     fprintf(stderr,
  366.         "segAlignment (%d) is not a multiple of the DEV_BYTES_PER_SECTOR.\n",
  367.         segAlignment);
  368.     exit(1);
  369.     }
  370.     segAlignment = segAlignment/DEV_BYTES_PER_SECTOR;
  371.  
  372.     if (maxCacheBlocksCleaned > maxNumCacheBlocks) {
  373.     fprintf(stderr, "maxCacheBlocksCleaned large than maxNumCacheBlocks\n");
  374.     exit(1);
  375.     } 
  376.  
  377.     /*
  378.      * Open of the device and write the file system.
  379.      */
  380.     diskFd = open(deviceName, O_RDWR, 0);
  381.     if (diskFd < 0) {
  382.     fprintf(stderr,"%s: ", argv[0]);
  383.     perror(deviceName);
  384.     exit(1);
  385.     }
  386.     sizeInSectors = ComputeDiskSize(diskFd);
  387.     if (numberSegments == -1) {
  388.     if (sizeInSectors < 0) {
  389.         fprintf(stderr,
  390.         "Can't compute disk size, must specified -numSegments\n");
  391.         exit(1);
  392.     }
  393.     /*
  394.      * Pack as many segments on to disk that will fit. Leave
  395.      * 128K at beginning for label, superblock, and checkpoint
  396.      * stuff.
  397.      */
  398.     numberSegments = (sizeInSectors*blockSize)/segmentSize - 
  399.                 ((128*1024)/segmentSize);
  400.     }
  401.     if (numberSegments < 0) {
  402.     fprintf(stderr,"Warning numberSegments (%d) < 0\n", numberSegments);
  403.     }
  404.  
  405.     if (maxDesc == -1) {
  406.     /*
  407.      * Unless otherwise told, generate one descriptor for
  408.      * every 8K of disk space.
  409.      */
  410.     maxDesc = (numberSegments * segmentSize) / 8192;
  411.     }
  412.  
  413.     /*
  414.      * Compute an upper bound of the checkpoint size. Checkpoint contains:
  415.      *        a checkpoint header.
  416.      *        as many as LFS_MAX_NUM_MODS check point regions.
  417.      *        a checkpoint trailer.
  418.      *        the desc map checkpoint info complete with block index.
  419.      *        the seg usage checkpoint info complete with block index.
  420.      *        some stats data.
  421.      */
  422.     maxCheckPointSize = sizeof(LfsCheckPointHdr) + 
  423.     sizeof(LfsCheckPointRegion) * LFS_MAX_NUM_MODS + 
  424.             sizeof(LfsCheckPointTrailer) +
  425.     sizeof(LfsDescMapCheckPoint) + sizeof(LfsStableMemCheckPoint) +
  426.     sizeof(int) * 
  427.         BlockCount(maxDesc*sizeof(LfsDescMapEntry),descMapBlockSize) +
  428.     sizeof(LfsSegUsageCheckPoint) +  sizeof(LfsStableMemCheckPoint) +
  429.         sizeof(int) * 
  430.         BlockCount(numberSegments*sizeof(LfsSegUsageEntry),usageArrayBlockSize)
  431.     + LFS_STATS_MAX_SIZE;
  432.  
  433.     /*
  434.      * Round to a multiple of the block size.
  435.      */
  436.     maxCheckPointBlocks = BlockCount(maxCheckPointSize,blockSize);
  437.     maxCheckPointSize = maxCheckPointBlocks * blockSize;
  438.     /*
  439.      * Fill in the super block header.
  440.      */
  441.     if (fstat(diskFd, &sbuf)) {
  442.     perror("Fstat of device failed");
  443.     exit(1);
  444.     }
  445.     partition = unix_minor(sbuf.st_rdev) & 7;
  446.     if (gettimeofday(&tod, NULL)) {
  447.     perror("gettimeofday failed");
  448.     exit(1);
  449.     }
  450.     startOffset = LFS_SUPER_BLOCK_OFFSET;
  451.     superBlockPtr = (LfsSuperBlock *) malloc(LFS_SUPER_BLOCK_SIZE);
  452.     bzero((char *)superBlockPtr, LFS_SUPER_BLOCK_SIZE);
  453.     superBlockPtr->hdr.magic = LFS_SUPER_BLOCK_MAGIC;
  454.     superBlockPtr->hdr.version = LFS_SUPER_BLOCK_VERSION;
  455.     superBlockPtr->hdr.blockSize = blockSize;
  456.     superBlockPtr->hdr.domainUID = tod.tv_sec;
  457.     superBlockPtr->hdr.partition = partition;
  458.     superBlockPtr->hdr.maxCheckPointBlocks = maxCheckPointBlocks;
  459.     superBlockPtr->hdr.checkpointInterval = checkpointInterval;
  460.     superBlockPtr->hdr.checkPointOffset[0] = startOffset + 
  461.             BlockCount(LFS_SUPER_BLOCK_SIZE, blockSize);
  462.     superBlockPtr->hdr.checkPointOffset[1]  = 
  463.     superBlockPtr->hdr.checkPointOffset[0] + maxCheckPointBlocks;
  464.     superBlockPtr->hdr.logStartOffset = 
  465.     superBlockPtr->hdr.checkPointOffset[1] +  maxCheckPointBlocks;
  466.     if ((superBlockPtr->hdr.logStartOffset % segAlignment) != 0) {
  467.     superBlockPtr->hdr.logStartOffset += 
  468.         (segAlignment - 
  469.             superBlockPtr->hdr.logStartOffset % segAlignment);
  470.     }
  471.     superBlockPtr->hdr.maxNumCacheBlocks = maxCacheBlocksCleaned;
  472.  
  473.     /*
  474.      * Reduce the number of segments until the file system fits on the disk.
  475.      */
  476.     if (sizeInSectors > 0) {
  477.     while ((superBlockPtr->hdr.logStartOffset + 
  478.         numberSegments * (segmentSize/blockSize)) *
  479.             blockSize/DEV_BYTES_PER_SECTOR >= sizeInSectors) {
  480.         numberSegments--;
  481.     }
  482.  
  483.     }
  484.     segMemPtr = calloc(1, segmentSize);
  485.  
  486.     summaryPtr = segMemPtr;
  487.  
  488.  
  489.     seg.startPtr = segMemPtr;
  490.     summaryPtr = segMemPtr + segmentSize - blockSize;
  491.     seg.dataPtr = summaryPtr;
  492.     seg.activeBytes = 0;
  493.     seg.diskAddress = superBlockPtr->hdr.logStartOffset;
  494.     seg.summaryPtr = summaryPtr + sizeof(LfsSegSummary) + 
  495.                 sizeof(LfsSegSummaryHdr);
  496.     checkPointPtr = calloc(1, maxCheckPointSize);
  497.     checkpoint.startPtr = checkPointPtr;
  498.     checkpoint.memPtr = checkPointPtr + sizeof(LfsCheckPointHdr) + 
  499.                      sizeof(LfsCheckPointRegion);
  500.     segSumPtr = (LfsSegSummary *) summaryPtr;
  501.     sumHdrPtr = (LfsSegSummaryHdr *) (summaryPtr + sizeof(LfsSegSummary));
  502.     regionPtr = (LfsCheckPointRegion *) 
  503.             (checkPointPtr + sizeof(LfsCheckPointHdr));
  504.     for (moduleType = LFS_FILE_LAYOUT_MOD; (moduleType < LFS_MAX_NUM_MODS);
  505.         moduleType++) { 
  506.     segMemPtr = seg.dataPtr;
  507.     if (moduleType == LFS_DESC_MAP_MOD) { 
  508.         BuildInitialDescMap(&superBlockPtr->descMap, &seg, &checkpoint);
  509.     } else if (moduleType == LFS_SEG_USAGE_MOD) {
  510.         BuildInitialUsageArray(&superBlockPtr->usageArray, &seg,
  511.                     &checkpoint);
  512.     } else if (moduleType == LFS_FILE_LAYOUT_MOD) {
  513.         BuildInitialFileLayout(&superBlockPtr->fileLayout, &seg, 
  514.                 &checkpoint);
  515.     } else {
  516.         panic("Unknown moduleType %d\n", moduleType);
  517.     }
  518.     sumHdrPtr->moduleType = moduleType;
  519.     sumHdrPtr->lengthInBytes = (seg.summaryPtr - (char *) sumHdrPtr); 
  520.     sumHdrPtr->numDataBlocks = (segMemPtr - seg.dataPtr)/blockSize;
  521.     sumHdrPtr = (LfsSegSummaryHdr *) seg.summaryPtr;
  522.     seg.summaryPtr += sizeof(LfsSegSummaryHdr);
  523.     regionPtr->type = moduleType;
  524.     regionPtr->size = (checkpoint.memPtr - (char *) regionPtr);
  525.  
  526.     regionPtr = (LfsCheckPointRegion *) checkpoint.memPtr;
  527.     checkpoint.memPtr += sizeof(LfsCheckPointRegion);
  528.     }
  529.     checkpoint.memPtr -= sizeof(LfsCheckPointRegion);
  530.     seg.summaryPtr -= sizeof(LfsSegSummaryHdr);
  531.  
  532.     ((LfsCheckPointTrailer *) checkpoint.memPtr)->timestamp = 1;
  533.     checkpoint.memPtr += sizeof(LfsCheckPointTrailer);
  534.     segSumPtr->magic = LFS_SEG_SUMMARY_MAGIC;
  535.     segSumPtr->timestamp = 1;
  536.     segSumPtr->prevSeg = 0;
  537.     segSumPtr->nextSeg = 1;
  538.     segSumPtr->size = (seg.summaryPtr - (char *) segSumPtr);
  539.     segSumPtr->nextSummaryBlock = -1;
  540.  
  541.     cpHdrPtr = (LfsCheckPointHdr *) checkpoint.startPtr;
  542.     cpHdrPtr->timestamp = 1;
  543.     cpHdrPtr->size = (checkpoint.memPtr - checkpoint.startPtr);
  544.     cpHdrPtr->version = 1;
  545.     cpHdrPtr->domainNumber = -1;
  546.     cpHdrPtr->attachSeconds = time(0);
  547.     cpHdrPtr->detachSeconds = time(0);
  548.     cpHdrPtr->serverID = serverID;
  549.     strncpy(cpHdrPtr->domainPrefix, prefix, 64);
  550.  
  551.     ((Lfs_StatsVersion1 *) checkpoint.memPtr)->size = sizeof(Lfs_StatsVersion1);
  552.     ((Lfs_StatsVersion1 *) checkpoint.memPtr)->version = 1;
  553.  
  554.     oldCheckPointPtr = (LfsCheckPointHdr *) calloc(1, blockSize);
  555.     oldCheckPointPtr->timestamp = 0;
  556.     oldCheckPointPtr->size = sizeof(LfsCheckPointHdr);
  557.     oldCheckPointPtr->version = 1;
  558.  
  559.     EraseOldFileSystem(diskFd);
  560.  
  561.     WriteDisk(diskFd, startOffset,(char *) superBlockPtr, LFS_SUPER_BLOCK_SIZE);
  562.     WriteDisk(diskFd, superBlockPtr->hdr.checkPointOffset[0],
  563.             checkPointPtr, maxCheckPointSize);
  564.     WriteDisk(diskFd, superBlockPtr->hdr.checkPointOffset[1], 
  565.             (char *) oldCheckPointPtr, sizeof(*oldCheckPointPtr));
  566.  
  567.     WriteDisk(diskFd, GetDiskAddressOf(&seg), seg.dataPtr, 
  568.             segmentSize - (seg.dataPtr - seg.startPtr));
  569.     bzero(segMemPtr, blockSize);
  570.     blocksPerSeg = segmentSize/blockSize;
  571.     for (segNum = 1; segNum < numberSegments; segNum++) {
  572.     WriteDisk(diskFd, superBlockPtr->hdr.logStartOffset +
  573.         blocksPerSeg * segNum + (blocksPerSeg-1), segMemPtr, 
  574.         blockSize);
  575.     }
  576.  
  577.     if (verbose) {
  578.     printf("maxNumCacheBlocks = %d\n", maxNumCacheBlocks);
  579.     printf("maxCacheBlocksCleaned = %d\n", maxCacheBlocksCleaned);
  580.     printf("maxUtilization = %d\n", maxUtilization);
  581.     printf("maxDesc = %d\n", maxDesc);
  582.     printf("segAlignment = %d\n", segAlignment);
  583.     printf("blockSize = %d\n", blockSize);
  584.     printf("segmentSize = %d\n", segmentSize);
  585.     printf("numSegments = %d\n", numberSegments);
  586.     printf("descBlockSize = %d\n", descBlockSize);
  587.     printf("descMapBlockSize = %d\n", descMapBlockSize);
  588.     printf("usageArrayBlockSize = %d\n", usageArrayBlockSize);
  589.     printf("\n");
  590.     printf("minNumClean = %d\n", superBlockPtr->usageArray.minNumClean);
  591.     printf("minFreeBlocks = %d\n", superBlockPtr->usageArray.minFreeBlocks);
  592.     printf("wasteBlocks = %d\n", superBlockPtr->usageArray.wasteBlocks);
  593.     printf("numSegsToClean = %d\n", superBlockPtr->usageArray.numSegsToClean);
  594.     }
  595.  
  596.     exit(0);
  597.     return 0;
  598. }
  599.  
  600. /*
  601.  *----------------------------------------------------------------------
  602.  *
  603.  * BuildInitialFileLayout --
  604.  *
  605.  *    Build the file structure for the file system. This consists of
  606.  *    initializing the root directory
  607.  *
  608.  * Results:
  609.  *    None.
  610.  *
  611.  * Side effects:
  612.  *    Directory is added to the segments.
  613.  *
  614.  *----------------------------------------------------------------------
  615.  */
  616.  
  617. static void
  618. BuildInitialFileLayout(fileLayoutPtr, segPtr, checkpointPtr)
  619.     LfsFileLayoutParams    *fileLayoutPtr;    /* File system params in super block to
  620.                      * be filled in. */
  621.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  622.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added. */
  623. {
  624.     LfsFileDescriptor    *descPtr;
  625.     LfsFileLayoutSummary *layoutSumPtr;
  626.     LfsFileLayoutDesc    *descLayoutPtr;
  627.  
  628.     /*
  629.      * Initialize the file layout parameters. 
  630.      */
  631.     fileLayoutPtr->descPerBlock = descBlockSize/sizeof(LfsFileDescriptor);
  632.     /*
  633.      * Allocate a descriptor block for the root directory's descriptor.
  634.      */
  635.     segPtr->dataPtr -= descBlockSize;
  636.     descPtr = (LfsFileDescriptor *) segPtr->dataPtr;
  637.  
  638.     segPtr->summaryPtr += sizeof(LfsFileLayoutDesc);
  639.     descLayoutPtr = (LfsFileLayoutDesc *) segPtr->summaryPtr;
  640.     descLayoutPtr->blockType = LFS_FILE_LAYOUT_DESC;
  641.     descLayoutPtr->numBlocks = descBlockSize/blockSize;
  642.     segPtr->activeBytes += 2*sizeof(LfsFileDescriptor);
  643.     root.descBlockAddress = GetDiskAddressOf(segPtr);
  644.  
  645.     MakeRootDir(descPtr+0, descPtr+1, segPtr, &root);
  646.     layoutSumPtr = (LfsFileLayoutSummary *) segPtr->summaryPtr;
  647.     segPtr->summaryPtr += sizeof(LfsFileLayoutSummary);
  648.     layoutSumPtr->blockType = LFS_FILE_LAYOUT_DATA;
  649.     layoutSumPtr->numBlocks = root.numBlocks;
  650.     layoutSumPtr->fileNumber = descPtr[0].fileNumber;
  651.     layoutSumPtr->truncVersion = root.truncVersion = 1;
  652.     layoutSumPtr->numDataBlocks = 1;
  653.     (*(int *) segPtr->summaryPtr) = 0;
  654.     segPtr->summaryPtr += sizeof(int);
  655.  
  656.     layoutSumPtr = (LfsFileLayoutSummary *) segPtr->summaryPtr;
  657.     segPtr->summaryPtr += sizeof(LfsFileLayoutSummary);
  658.     layoutSumPtr->blockType = LFS_FILE_LAYOUT_DATA;
  659.     layoutSumPtr->numBlocks = root.numBlocks;
  660.     layoutSumPtr->fileNumber = descPtr[1].fileNumber;
  661.     layoutSumPtr->truncVersion = root.truncVersion;
  662.     layoutSumPtr->numDataBlocks = 1;
  663.  
  664.     (*(int *) segPtr->summaryPtr) = 0;
  665.     segPtr->summaryPtr += sizeof(int);
  666.  
  667. }
  668.  
  669.  
  670. /*
  671.  *----------------------------------------------------------------------
  672.  *
  673.  * BuildInitialDescMap --
  674.  *
  675.  *    Build the initial descriptor structure for a file system.
  676.  *
  677.  * Results:
  678.  *    None.
  679.  *
  680.  * Side effects:
  681.  *    None.
  682.  *
  683.  *----------------------------------------------------------------------
  684.  */
  685.  
  686. void
  687. BuildInitialDescMap(descParamsPtr, segPtr, checkpointPtr)
  688.     LfsDescMapParams    *descParamsPtr; /* Parameters in super block to be 
  689.                      * filled in. */
  690.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  691.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added. */
  692. {
  693.     LfsDescMapCheckPoint    *cp;
  694.     StableMem            *stableMemPtr;
  695.  
  696.     descParamsPtr->version = LFS_DESC_MAP_VERSION;
  697.     descParamsPtr->maxDesc = maxDesc;
  698.     if (maxDesc<0) {
  699.     fprintf(stderr,"Warning: maxDesc (%d) < 0\n", maxDesc);
  700.     }
  701.  
  702.     stableMemPtr = BuildStableMem(LFS_DESC_MAP_MOD, descMapBlockSize, 
  703.            sizeof(LfsDescMapEntry),  maxDesc,
  704.            &(descParamsPtr->stableMem));
  705.  
  706.     /*
  707.      * Reserve descriptors 0 and 1.
  708.      */
  709.     SetDescriptorMap(stableMemPtr, 0, 0, 0, 0);
  710.     SetDescriptorMap(stableMemPtr, 1, 0, 0, 0); 
  711.     SetDescriptorMap(stableMemPtr, FSDM_ROOT_FILE_NUMBER, 
  712.             root.descBlockAddress, 
  713.             root.truncVersion, root.accessTime);
  714.     SetDescriptorMap(stableMemPtr, FSDM_LOST_FOUND_FILE_NUMBER, 
  715.             root.descBlockAddress, 
  716.             root.truncVersion, root.accessTime);
  717.  
  718.     cp = (LfsDescMapCheckPoint *) checkpointPtr->memPtr;
  719.     cp->numAllocDesc = 4;
  720.     checkpointPtr->memPtr += sizeof(LfsDescMapCheckPoint);
  721.     LayoutStableMem(stableMemPtr, segPtr, checkpointPtr);
  722. }
  723.  
  724.  
  725. /*
  726.  *----------------------------------------------------------------------
  727.  *
  728.  * BuildInitialUsageArray --
  729.  *
  730.  *    Build the initial usage array structure for the file system.
  731.  *
  732.  * Results:
  733.  *    None.
  734.  *
  735.  * Side effects:
  736.  *    None.
  737.  *
  738.  *----------------------------------------------------------------------
  739.  */
  740.  
  741. void
  742. BuildInitialUsageArray(usagePtr, segPtr, checkpointPtr)
  743.     LfsSegUsageParams    *usagePtr;      /* Parameters in super block to be 
  744.                      * filled in. */
  745.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  746.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added to. */
  747. {
  748.     LfsSegUsageCheckPoint    *cp;
  749.     LfsSegUsageEntry        entry;
  750.     int                i, numBlocks;
  751.     StableMem        *stableMemPtr;
  752.  
  753.     usagePtr->segmentSize = segmentSize;
  754.     usagePtr->numberSegments = numberSegments;
  755.     /*
  756.      * Set the minimum number of clean segments that we allow the system
  757.      * to get to before starting cleaning. We shouldn't let this 
  758.      * number get any smaller than the size of the data we clean.
  759.      * We make it two times this number to add a margin of safety.
  760.      * 
  761.      */
  762.     usagePtr->minNumClean = 2*(FS_BLOCK_SIZE * (maxCacheBlocksCleaned))
  763.                 /  segmentSize;
  764.     if (usagePtr->minNumClean < 10) {
  765.     usagePtr->minNumClean = 10;
  766.     }
  767.     numBlocks = numberSegments * (segmentSize/blockSize);
  768.     /*
  769.      * Set the minimum number of free blocks allowed. This should be
  770.      * based on the max disk space utilization required of the disk.
  771.      * For very small disk this number may be dominated by the minNumClean
  772.      * value.
  773.      */
  774.     usagePtr->minFreeBlocks = (int) (numBlocks - (numBlocks * maxUtilization));
  775.     if (usagePtr->minFreeBlocks < 
  776.         (usagePtr->minNumClean+10)*(segmentSize/blockSize)) {
  777.     usagePtr->minFreeBlocks = 
  778.         (usagePtr->minNumClean+10)*(segmentSize/blockSize);
  779.     }
  780.  
  781.     if (numBlocks < usagePtr->minFreeBlocks) {
  782.     fprintf(stderr,"Warning: numblocks < minFreeBlocks (%d vs %d)\n",
  783.         numBlocks, usagePtr->minFreeBlocks);
  784.     }
  785.  
  786.     usagePtr->wasteBlocks = (FS_BLOCK_SIZE/blockSize) + 2;
  787.  
  788.     /* 
  789.      * Number of segments to clean before stoping because there is
  790.      * until already clean. We clean enough to write back the
  791.      * entire file cache. 
  792.      */
  793.     usagePtr->numSegsToClean = 1+(maxNumCacheBlocks*FS_BLOCK_SIZE)/segmentSize;
  794.     if (usagePtr->numSegsToClean + usagePtr->minNumClean >= 
  795.         (int) (numberSegments*maxUtilization)) {
  796.     usagePtr->numSegsToClean = (int) (numberSegments*maxUtilization) - 
  797.                         usagePtr->minNumClean - 10;
  798.     if (usagePtr->numSegsToClean<=0) {
  799.         fprintf(stderr,"Warning: numSegsToClean = %d\n",
  800.             usagePtr->numSegsToClean);
  801.     }
  802.     }
  803.  
  804.  
  805.     stableMemPtr = BuildStableMem(LFS_SEG_USAGE_MOD, usageArrayBlockSize, 
  806.            sizeof(LfsSegUsageEntry),  numberSegments,
  807.            &(usagePtr->stableMem));
  808.  
  809.     /*
  810.      * Link all clean segments togther. 
  811.      */
  812.     entry.activeBytes = 0;
  813.     entry.flags = LFS_SEG_USAGE_DIRTY;
  814.     UpdateStableMem(stableMemPtr, 0, (char *) &entry);
  815.  
  816.     for (i = 1; i < numberSegments; i++) {
  817.     entry.activeBytes = i+1;
  818.     entry.flags = LFS_SEG_USAGE_CLEAN;
  819.     UpdateStableMem(stableMemPtr, i, (char *) &entry);
  820.     }
  821.     entry.activeBytes = NIL;
  822.     entry.flags = LFS_SEG_USAGE_CLEAN;
  823.     UpdateStableMem(stableMemPtr, numberSegments-1, (char *) &entry);
  824.  
  825.     cp = (LfsSegUsageCheckPoint *) checkpointPtr->memPtr;
  826.     cp->numClean = numberSegments-1;
  827.     cp->numDirty = 1;
  828.     cp->dirtyActiveBytes = (int) (segmentSize * segFullLevel);
  829.     cp->currentSegment = 0;
  830.     cp->currentBlockOffset = -1;
  831.     checkpointPtr->memPtr += sizeof(LfsSegUsageCheckPoint);
  832.     LayoutStableMem(stableMemPtr, segPtr, checkpointPtr);
  833.     cp->curSegActiveBytes = segPtr->activeBytes;
  834.     cp->previousSegment = -1;
  835.     cp->cleanSegList = 1;
  836.     cp->freeBlocks = numberSegments*(segmentSize/blockSize) - 
  837.              (segPtr->activeBytes + blockSize - 1)/blockSize;
  838. }
  839.  
  840. /*
  841.  *----------------------------------------------------------------------
  842.  *
  843.  * BuildStableMem --
  844.  *
  845.  *    Build the stable memory map.
  846.  *
  847.  * Results:
  848.  *    A StableMem structure that can be used to calls to UpdateStableMem
  849.  *    and LayoutStableMem.
  850.  *
  851.  * Side effects:
  852.  *    None.
  853.  *
  854.  *----------------------------------------------------------------------
  855.  */
  856.  
  857. static StableMem *
  858. BuildStableMem(memType, memBlockSize, entrySize, maxNumEntries, smemParamsPtr)
  859.     int     memType;    /* Type number of stable memory map. */
  860.     int     memBlockSize;    /* Block size of the memory. */
  861.     int     entrySize;    /* Size of each entry in bytes. */
  862.     int     maxNumEntries; /* Maximum number of entries supported. */
  863.     LfsStableMemParams *smemParamsPtr; /* Stable mem params to fill in. */
  864. {
  865.     StableMem            *stableMemPtr;
  866.  
  867.     /*
  868.      * Fill in the params for this map.
  869.      */
  870.     if (maxNumEntries<=0) {
  871.     fprintf(stderr,"Warning:maxNumEntries (%d) < 0\n", maxNumEntries);
  872.     }
  873.     if (entrySize<=0) {
  874.     fprintf(stderr,"Warning:entrySize (%d) < 0\n", entrySize);
  875.     }
  876.     smemParamsPtr->memType = memType;
  877.     smemParamsPtr->blockSize = memBlockSize;
  878.     smemParamsPtr->entrySize = entrySize;
  879.     smemParamsPtr->maxNumEntries = maxNumEntries;
  880.  
  881.     smemParamsPtr->entriesPerBlock = 
  882.         (memBlockSize - sizeof(LfsStableMemBlockHdr)) / entrySize;
  883.     smemParamsPtr->maxNumBlocks = BlockCount(maxNumEntries, 
  884.                     smemParamsPtr->entriesPerBlock);
  885.  
  886.     stableMemPtr = (StableMem *) calloc(1, sizeof(StableMem));
  887.     stableMemPtr->paramsPtr = smemParamsPtr;
  888.     stableMemPtr->blockPtrs = (char **) malloc(sizeof(char *) * 
  889.                         smemParamsPtr->maxNumBlocks);
  890.  
  891.     bzero((char *) stableMemPtr->blockPtrs, sizeof(char *) * 
  892.                         smemParamsPtr->maxNumBlocks);
  893.  
  894.     return stableMemPtr;
  895. }
  896.  
  897. /*
  898.  *----------------------------------------------------------------------
  899.  *
  900.  * UpdateStableMem --
  901.  *
  902.  *    Update an entry in a stable memory data structure.
  903.  *
  904.  * Results:
  905.  *    None.
  906.  *
  907.  * Side effects:
  908.  *    None.
  909.  *
  910.  *----------------------------------------------------------------------
  911.  */
  912. static void
  913. UpdateStableMem(stableMemPtr, entryNumber, entryPtr)
  914.     StableMem    *stableMemPtr;        /* Stable memory data to update. */
  915.     int        entryNumber;    /* Entry number to upate. */
  916.     char    *entryPtr;    /* New value for entry entryNumber. */
  917. {
  918.     int         blockNum, offset;
  919.     LfsStableMemBlockHdr *hdrPtr;
  920.  
  921.     if ((entryNumber < 0) || 
  922.     (entryNumber >= stableMemPtr->paramsPtr->maxNumEntries)) {
  923.     panic("Entry number out of range\n");
  924.     }
  925.  
  926.     blockNum = entryNumber / stableMemPtr->paramsPtr->entriesPerBlock;
  927.     offset = (entryNumber % stableMemPtr->paramsPtr->entriesPerBlock) * 
  928.         stableMemPtr->paramsPtr->entrySize + 
  929.                 sizeof(LfsStableMemBlockHdr);
  930.  
  931.     if (stableMemPtr->blockPtrs[blockNum] == (char *) NULL) {
  932.     stableMemPtr->blockPtrs[blockNum] = 
  933.                 calloc(1, stableMemPtr->paramsPtr->blockSize);
  934.     hdrPtr = (LfsStableMemBlockHdr *) stableMemPtr->blockPtrs[blockNum];
  935.     hdrPtr->magic = LFS_STABLE_MEM_BLOCK_MAGIC;
  936.     hdrPtr->memType = stableMemPtr->paramsPtr->memType;
  937.     hdrPtr->blockNum = blockNum;
  938.     }
  939.     bcopy(entryPtr, stableMemPtr->blockPtrs[blockNum] + offset, 
  940.       stableMemPtr->paramsPtr->entrySize);
  941.  
  942. }
  943.  
  944. /*
  945.  *----------------------------------------------------------------------
  946.  *
  947.  * LayoutStableMem --
  948.  *
  949.  *    Add to a segment the contents of a stable memory data structure.
  950.  *
  951.  * Results:
  952.  *    None.
  953.  *
  954.  * Side effects:
  955.  *    Data, summary, and checkpoint region added to.
  956.  *
  957.  *----------------------------------------------------------------------
  958.  */
  959.  
  960. static void
  961. LayoutStableMem(stableMemPtr, segPtr, checkpointPtr)
  962.     StableMem    *stableMemPtr;        /* Stable memory data to layout. */
  963.     SegMem        *segPtr;    /* Segment to add data blocks to. */
  964.     CheckPointMem    *checkpointPtr; /* Checkpoint info to be added to. */
  965. {
  966.     LfsStableMemCheckPoint    *cp;
  967.     int    block;
  968.  
  969.     cp = (LfsStableMemCheckPoint *) checkpointPtr->memPtr;
  970.     cp->numBlocks = 0;
  971.     checkpointPtr->memPtr += sizeof(LfsStableMemCheckPoint);
  972.     for (block = 0; block < stableMemPtr->paramsPtr->maxNumBlocks; block++) { 
  973.     if (stableMemPtr->blockPtrs[block]) {
  974.         segPtr->dataPtr -= stableMemPtr->paramsPtr->blockSize;
  975.         segPtr->activeBytes += stableMemPtr->paramsPtr->blockSize;
  976.         bcopy(stableMemPtr->blockPtrs[block],segPtr->dataPtr, 
  977.             stableMemPtr->paramsPtr->blockSize);
  978.         *((int *) (segPtr->summaryPtr)) = block;
  979.         segPtr->summaryPtr += sizeof(int);
  980.         cp->numBlocks++;
  981.         *((int *) (checkpointPtr->memPtr)) = 
  982.             GetDiskAddressOf(segPtr);
  983.         checkpointPtr->memPtr += sizeof(int);
  984.      } else {
  985.         *((int *) (checkpointPtr->memPtr)) = FSDM_NIL_INDEX;
  986.         checkpointPtr->memPtr += sizeof(int);
  987.      }
  988.     }
  989. }
  990.  
  991. /*
  992.  *----------------------------------------------------------------------
  993.  *
  994.  * MakeRootDir --
  995.  *
  996.  *    Make the initial root directory of a LFS file system..
  997.  *
  998.  * Results:
  999.  *    None.
  1000.  *
  1001.  * Side effects:
  1002.  *    Data and summary blocks added to the segment.
  1003.  *
  1004.  *----------------------------------------------------------------------
  1005.  */
  1006. static void
  1007. MakeRootDir(rootDescPtr, lostDescPtr, segPtr, rootPtr)
  1008.     LfsFileDescriptor *rootDescPtr;  /* Root file descriptor to fill in. */
  1009.     LfsFileDescriptor *lostDescPtr; /* Lost an found descriptor to fill 
  1010.                        * in. */
  1011.     SegMem        *segPtr;     /* Segment to add directory to. */
  1012.     RootDir        *rootPtr;    /* Root directory info. */
  1013. {
  1014.     Fslcl_DirEntry *dirEntryPtr;
  1015.     char *fileName, *dirPtr;
  1016.     int length,  offset;
  1017.  
  1018.     FileDescInit(rootDescPtr, FSDM_ROOT_FILE_NUMBER, FS_DIRECTORY);
  1019.     FileDescInit(lostDescPtr, FSDM_LOST_FOUND_FILE_NUMBER, FS_DIRECTORY);
  1020.     segPtr->dataPtr -= FSLCL_DIR_BLOCK_SIZE;
  1021.     segPtr->activeBytes += FSLCL_DIR_BLOCK_SIZE;
  1022.     dirPtr = segPtr->dataPtr;
  1023.     rootDescPtr->common.lastByte = FSLCL_DIR_BLOCK_SIZE-1;
  1024.     rootDescPtr->common.direct[0] = GetDiskAddressOf(segPtr);
  1025.     rootDescPtr->common.numKbytes = 1;
  1026.     /*
  1027.      * Place the data in the first filesystem block.
  1028.      */
  1029.     dirEntryPtr = (Fslcl_DirEntry *) dirPtr;
  1030.  
  1031.     fileName = ".";
  1032.     length = strlen(fileName);
  1033.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  1034.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  1035.     dirEntryPtr->nameLength = length;
  1036.     strcpy(dirEntryPtr->fileName, fileName);
  1037.     offset = dirEntryPtr->recordLength;
  1038.     rootDescPtr->common.numLinks++;
  1039.  
  1040.     dirEntryPtr = (Fslcl_DirEntry *)(dirPtr + offset);
  1041.     fileName = "..";
  1042.     length = strlen(fileName);
  1043.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  1044.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  1045.     dirEntryPtr->nameLength = length;
  1046.     strcpy(dirEntryPtr->fileName, fileName);
  1047.     offset += dirEntryPtr->recordLength;
  1048.     rootDescPtr->common.numLinks++;
  1049.  
  1050.     dirEntryPtr = (Fslcl_DirEntry *)(dirPtr + offset);
  1051.     fileName = "lost+found";
  1052.     length = strlen(fileName);
  1053.     dirEntryPtr->fileNumber = FSDM_LOST_FOUND_FILE_NUMBER;
  1054.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  1055.     dirEntryPtr->nameLength = length;
  1056.     strcpy(dirEntryPtr->fileName, fileName);
  1057.     lostDescPtr->common.numLinks++;
  1058.  
  1059.  
  1060.  
  1061.     /*
  1062.      * Initialized and add to the segment the lost+found directory. 
  1063.      */
  1064.     segPtr->dataPtr -= FSLCL_DIR_BLOCK_SIZE;
  1065.     segPtr->activeBytes += FSLCL_DIR_BLOCK_SIZE;
  1066.     dirPtr = segPtr->dataPtr;
  1067.     lostDescPtr->common.lastByte = FSLCL_DIR_BLOCK_SIZE-1;
  1068.     lostDescPtr->common.direct[0] = GetDiskAddressOf(segPtr);
  1069.     lostDescPtr->common.numKbytes = 1;
  1070.     /*
  1071.      * Fill in the directory.
  1072.      */
  1073.     dirEntryPtr = (Fslcl_DirEntry *) dirPtr;
  1074.     fileName = ".";
  1075.     length = strlen(fileName);
  1076.     dirEntryPtr->fileNumber = FSDM_LOST_FOUND_FILE_NUMBER;
  1077.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  1078.     dirEntryPtr->nameLength = length;
  1079.     strcpy(dirEntryPtr->fileName, fileName);
  1080.     offset = dirEntryPtr->recordLength;
  1081.     lostDescPtr->common.numLinks++;
  1082.  
  1083.     dirEntryPtr = (Fslcl_DirEntry *)(dirPtr + offset);
  1084.     fileName = "..";
  1085.     length = strlen(fileName);
  1086.     dirEntryPtr->fileNumber = FSDM_ROOT_FILE_NUMBER;
  1087.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  1088.     dirEntryPtr->nameLength = length;
  1089.     strcpy(dirEntryPtr->fileName, fileName);
  1090.     rootDescPtr->common.numLinks++;
  1091.  
  1092.     rootPtr->accessTime = rootDescPtr->common.accessTime;
  1093.     rootPtr->numBlocks = FSLCL_DIR_BLOCK_SIZE/blockSize;
  1094.     return;
  1095. }
  1096.  
  1097. /*
  1098.  *----------------------------------------------------------------------
  1099.  *
  1100.  * FileDescInit --
  1101.  *
  1102.  *    Initialized a LFS file descriptor.
  1103.  *
  1104.  * Results:
  1105.  *    None.
  1106.  *
  1107.  * Side effects:
  1108.  *    None.
  1109.  *
  1110.  *----------------------------------------------------------------------
  1111.  */
  1112.  
  1113. static void
  1114. FileDescInit(fileDescPtr, fileNumber, fileType)
  1115.     LfsFileDescriptor *fileDescPtr;     /* File descriptor to fill in. */
  1116.     int              fileNumber;    /* File number of descriptor. */
  1117.     int              fileType;        /* File type of the desc. */
  1118. {
  1119.     int  timeVal, index;
  1120.  
  1121.     fileDescPtr->fileNumber = fileNumber;
  1122.     fileDescPtr->common.magic = FSDM_FD_MAGIC;
  1123.     fileDescPtr->common.flags = FSDM_FD_ALLOC;
  1124.     fileDescPtr->common.fileType = fileType;
  1125.     fileDescPtr->common.permissions = 0755;
  1126.     fileDescPtr->common.uid = 0;
  1127.     fileDescPtr->common.gid = 0;
  1128.     fileDescPtr->common.lastByte = -1;
  1129.     fileDescPtr->common.firstByte = -1;
  1130.     fileDescPtr->common.numLinks = 0;
  1131.     /*
  1132.      * Can't know device information because that depends on
  1133.      * the way the system is configured.
  1134.      */
  1135.     fileDescPtr->common.devServerID = -1;
  1136.     fileDescPtr->common.devType = -1;
  1137.     fileDescPtr->common.devUnit = -1;
  1138.  
  1139.     /*
  1140.      * Set the time stamps.  This assumes that universal time, not local
  1141.      * time, is used for time stamps.
  1142.      */
  1143.     timeVal = time(0);
  1144.     fileDescPtr->common.createTime = timeVal;
  1145.     fileDescPtr->common.accessTime = timeVal;
  1146.     fileDescPtr->common.descModifyTime = timeVal;
  1147.     fileDescPtr->common.dataModifyTime = timeVal;
  1148.  
  1149.     /*
  1150.      * Initialize map to NILs.
  1151.      */
  1152.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  1153.     fileDescPtr->common.direct[index] = FSDM_NIL_INDEX;
  1154.     }
  1155.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  1156.     fileDescPtr->common.indirect[index] = FSDM_NIL_INDEX;
  1157.     }
  1158.     fileDescPtr->common.numKbytes = 0;
  1159.     fileDescPtr->common.version = 1;
  1160. }
  1161.  
  1162. /*
  1163.  *----------------------------------------------------------------------
  1164.  *
  1165.  * SetDescriptorMap --
  1166.  *
  1167.  *    Set an entry in the descriptor map of the file system. 
  1168.  *
  1169.  * Results:
  1170.  *    None.
  1171.  *
  1172.  * Side effects:
  1173.  *    None.
  1174.  *
  1175.  *----------------------------------------------------------------------
  1176.  */
  1177.  
  1178. static void
  1179. SetDescriptorMap(stableMemPtr, fileNumber, diskAddress, truncVersion, 
  1180.             accessTime)
  1181.     StableMem    *stableMemPtr;   /* Stable memory of descriptor map. */
  1182.     int    fileNumber;         /* File number to set. */
  1183.     unsigned int diskAddress;    /* Disk address of file number. */
  1184.     int truncVersion;         /* Truncate version number of file. */
  1185.     int    accessTime;         /* Time of last file access. */
  1186. {
  1187.     LfsDescMapEntry entry;
  1188.  
  1189.     entry.blockAddress = diskAddress;
  1190.     entry.truncVersion = truncVersion;
  1191.     entry.flags = LFS_DESC_MAP_ALLOCED;
  1192.     entry.accessTime = accessTime;
  1193.     UpdateStableMem(stableMemPtr, fileNumber, (char *) &entry);
  1194. }
  1195.  
  1196. /*
  1197.  *----------------------------------------------------------------------
  1198.  *
  1199.  * GetDiskAddressOf --
  1200.  *
  1201.  *    Return the disk address of the current data pointer of the segment.
  1202.  *
  1203.  * Results:
  1204.  *    The disk address of last data block allocated.
  1205.  *
  1206.  * Side effects:
  1207.  *    None.
  1208.  *
  1209.  *----------------------------------------------------------------------
  1210.  */
  1211. static unsigned int 
  1212. GetDiskAddressOf(segPtr)
  1213.     SegMem    *segPtr;    /* Return the disk address of the current
  1214.                  * dataPtr. */
  1215. {
  1216.     int blockOffset;
  1217.     blockOffset = (segPtr->dataPtr - segPtr->startPtr) / blockSize;
  1218.     return segPtr->diskAddress + blockOffset;
  1219. }
  1220.  
  1221. /*
  1222.  *----------------------------------------------------------------------
  1223.  *
  1224.  * WriteDisk --
  1225.  *
  1226.  *    Write the the sepcified buffer to disk.
  1227.  *
  1228.  * Results:
  1229.  *    None.
  1230.  *
  1231.  * Side effects:
  1232.  *    This disk gets written or the program exits.
  1233.  *
  1234.  *----------------------------------------------------------------------
  1235.  */
  1236.  
  1237. static void
  1238. WriteDisk(diskFd, blockOffset, bufferPtr, bufferSize)
  1239.     int    diskFd;        /* Open file descriptor of disk. */
  1240.     int    blockOffset;    /* Block offset into disk to write. */
  1241.     char *bufferPtr;    /* Buffer to write. */
  1242.     int     bufferSize;    /* Number of bytes to write. */
  1243. {
  1244.     int    numBytes, status;
  1245.  
  1246.     numBytes = BlockCount(bufferSize, blockSize) * blockSize;
  1247.  
  1248.     status = lseek(diskFd, blockOffset*blockSize, L_SET);
  1249.     if (status < 0) {
  1250.     fprintf(stderr,"Writing device: ");
  1251.     perror("lseek");
  1252.     exit(1);
  1253.     }
  1254.     status = write(diskFd, bufferPtr, numBytes);
  1255.     if (status != numBytes) {
  1256.     if (status < 0) {
  1257.         fprintf(stderr,"Writing device: ");
  1258.         perror("write");
  1259.         exit(1);
  1260.     }
  1261.     fprintf(stderr,"Short write on device %d != %d\n", status, numBytes);
  1262.     exit(1);
  1263.     }
  1264.  
  1265. }
  1266.  
  1267. /*
  1268.  *----------------------------------------------------------------------
  1269.  *
  1270.  * IsPowerOfTwo --
  1271.  *
  1272.  *    Check to see if the integer is a postive power of two.
  1273.  *
  1274.  * Results:
  1275.  *    TRUE if the argument is a power of two. FALSE otherwise.
  1276.  *
  1277.  * Side effects:
  1278.  *    None.
  1279.  *
  1280.  *----------------------------------------------------------------------
  1281.  */
  1282.  
  1283. static Boolean
  1284. IsPowerOfTwo(ival)
  1285.     int     ival;    /* Value to check. */
  1286. {
  1287.     if (ival <= 0) {
  1288.     return FALSE;
  1289.     }
  1290.     while (!(ival & 1)) {
  1291.     ival >>= 1;
  1292.     }
  1293.     return ((ival >> 1) == 0);
  1294. }
  1295.  
  1296. /*
  1297.  *----------------------------------------------------------------------
  1298.  *
  1299.  * IsMultipleOf --
  1300.  *
  1301.  *    Check to see if one integer is a multiple of another..
  1302.  *
  1303.  * Results:
  1304.  *    TRUE if they are multiples. FALSE otherwise.
  1305.  *
  1306.  * Side effects:
  1307.  *    None.
  1308.  *
  1309.  *----------------------------------------------------------------------
  1310.  */
  1311.  
  1312. static Boolean
  1313. IsMultipleOf(imultiple, ival)
  1314.     int    imultiple;    /* Value to check against ival. */
  1315.     int ival;        /* Base value. */
  1316. {
  1317.     int    itemp;
  1318.  
  1319.     itemp = imultiple/ival;
  1320.  
  1321.     return (itemp*ival == imultiple);
  1322. }
  1323.  
  1324.  
  1325. /*
  1326.  *----------------------------------------------------------------------
  1327.  *
  1328.  * BlockCount  --
  1329.  *
  1330.  *    Return how many blocks of a specified size it will take to 
  1331.  *    the specified object.
  1332.  *
  1333.  * Results:
  1334.  *    Number of blocks.
  1335.  *
  1336.  * Side effects:
  1337.  *    None.
  1338.  *
  1339.  *----------------------------------------------------------------------
  1340.  */
  1341.  
  1342. static int
  1343. BlockCount(objectSize, blockSize)
  1344.     int    objectSize;    /* Size of object in bytes. */
  1345.     int blockSize;    /* Block size in bytes. */
  1346. {
  1347.  
  1348.     return (objectSize + (blockSize-1))/blockSize;
  1349. }
  1350.  
  1351. #include <disk.h>
  1352.  
  1353. /*
  1354.  *----------------------------------------------------------------------
  1355.  *
  1356.  * EraseOldFileSystem --
  1357.  *
  1358.  *    Erase the old OFS file system from the disk so that the kernel
  1359.  *    attach code wont file it.
  1360.  *
  1361.  * Results:
  1362.  *    None.
  1363.  *
  1364.  * Side effects:
  1365.  *    None.
  1366.  *
  1367.  *----------------------------------------------------------------------
  1368.  */
  1369.  
  1370. static void
  1371. EraseOldFileSystem(diskFd)
  1372.     int    diskFd;    /* Open file descriptor of disk. */
  1373. {
  1374.     Disk_Label  *labelPtr;
  1375.     int        status, i;
  1376.     static    char bufferOfZeros[DEV_BYTES_PER_SECTOR];
  1377.  
  1378.     labelPtr = Disk_ReadLabel(diskFd);
  1379.     if (labelPtr == (Disk_Label *) NULL) {
  1380.     return;
  1381.     }
  1382.     if (labelPtr->summarySector > 0) {
  1383.     status = lseek(diskFd, 
  1384.             DEV_BYTES_PER_SECTOR*labelPtr->summarySector, L_SET);
  1385.     if (status > 0) {
  1386.         status = write(diskFd, bufferOfZeros, DEV_BYTES_PER_SECTOR);
  1387.     }
  1388.     if (status < 0) {
  1389.         fprintf(stderr,"Erasing old file system: ");
  1390.         perror("write");
  1391.     }
  1392.     }
  1393.     if (labelPtr->domainSector > 0) {
  1394.     for (i = 0; i < labelPtr->numDomainSectors; i++) {
  1395.         status = lseek(diskFd, 
  1396.             DEV_BYTES_PER_SECTOR*(labelPtr->domainSector+i), L_SET);
  1397.         if (status > 0) {
  1398.         status = write(diskFd, bufferOfZeros, DEV_BYTES_PER_SECTOR);
  1399.         }
  1400.         if (status < 0) {
  1401.         fprintf(stderr,"Erasing old file system: ");
  1402.         perror("write");
  1403.         }
  1404.      }
  1405.  
  1406.     }
  1407. }
  1408.  
  1409. /*
  1410.  *----------------------------------------------------------------------
  1411.  *
  1412.  * ComputeDiskSize --
  1413.  *
  1414.  *    Compute the size of the disk by reading it from the disk label.
  1415.  *
  1416.  * Results:
  1417.  *    -1 if can't compute size.  The size.
  1418.  *
  1419.  * Side effects:
  1420.  *    None.
  1421.  *
  1422.  *----------------------------------------------------------------------
  1423.  */
  1424. static int
  1425. ComputeDiskSize(diskFd)
  1426.     int    diskFd;    /* Open file descriptor of disk. */
  1427. {
  1428.     struct stat sbuf;
  1429.     Disk_Label  *labelPtr;
  1430.     int        partition, sizeInSectors;
  1431.  
  1432.     labelPtr = Disk_ReadLabel(diskFd);
  1433.     if (labelPtr == (Disk_Label *) NULL) {
  1434.     printf("Couldn't read label\n");
  1435.     return -1;
  1436.     }
  1437.     if (fstat(diskFd, &sbuf) < 0) {
  1438.     printf("Couldn't stat disk\n");
  1439.     return -1;
  1440.     }
  1441. #ifdef ds3100
  1442.     /*
  1443.      * Handle some bogusness in the ds3100 port.
  1444.      */
  1445.     partition = unix_minor(sbuf.st_rdev) & 0x7;
  1446. #else
  1447.     partition = minor(sbuf.st_rdev) & 0x7;
  1448. #endif
  1449.     sizeInSectors = labelPtr->partitions[partition].numCylinders * 
  1450.             labelPtr->numHeads * labelPtr->numSectors;
  1451.     if (sizeInSectors <= 0) {
  1452.     printf("label gives bad size: %d cyl, %d head, %d sectors\n",
  1453.         labelPtr->partitions[partition].numCylinders,
  1454.         labelPtr->numHeads, labelPtr->numSectors);
  1455.     sizeInSectors = -1;
  1456.     }
  1457.     return sizeInSectors;
  1458. }
  1459. @
  1460.  
  1461.  
  1462. 1.4
  1463. log
  1464. @got rid of bogus include
  1465. @
  1466. text
  1467. @d17 1
  1468. a17 1
  1469. static char rcsid[] = "$Header: /sprite/src/admin/mklfs/RCS/mklfs.c,v 1.3 91/12/17 22:14:21 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  1470. d142 1
  1471. d184 1
  1472. d357 3
  1473. d533 19
  1474. d654 3
  1475. d737 5
  1476. d754 4
  1477. d826 6
  1478. d1390 1
  1479. d1394 1
  1480. d1408 3
  1481. @
  1482.  
  1483.  
  1484. 1.3
  1485. log
  1486. @sets partition and domainUID fields in the superblock. Also allows the user to set the domainPrefix field.
  1487. @
  1488. text
  1489. @d17 1
  1490. a17 1
  1491. static char rcsid[] = "$Header: /sprite/src/admin/mklfs/RCS/mklfs.c,v 1.2 91/12/17 15:04:21 mendel Exp Locker: jhh $ SPRITE (Berkeley)";
  1492. a57 1
  1493. #if 0
  1494. a58 2
  1495. #endif
  1496. #include "/sprite/src/kernel/jhh/src/lfs/lfsSuperBlock.h"
  1497. @
  1498.  
  1499.  
  1500. 1.2
  1501. log
  1502. @checking these in for mendel -- jhh
  1503. @
  1504. text
  1505. @d17 1
  1506. a17 1
  1507. static char rcsid[] = "$Header: /sprite/src/admin/mklfs/RCS/mklfs.c,v 1.1 91/05/31 11:09:07 mendel Exp $ SPRITE (Berkeley)";
  1508. d43 1
  1509. d58 1
  1510. d60 2
  1511. d150 4
  1512. d157 1
  1513. a157 1
  1514. "This program generates an empty LFS file system. WARNING: This command\n will overwrite any existing data or file system on the specified device.\n Synopsis: \"mklfs [switches] deviceName\"\n Command-line switches are:"},
  1515. d259 3
  1516. a262 1
  1517.  
  1518. d278 1
  1519. a278 1
  1520.     if (argc != 2) { 
  1521. d281 8
  1522. a288 2
  1523.     } else {
  1524.     deviceName = argv[1];
  1525. d395 9
  1526. d410 2
  1527. d503 1
  1528. @
  1529.  
  1530.  
  1531. 1.1
  1532. log
  1533. @Initial revision
  1534. @
  1535. text
  1536. @d17 1
  1537. a17 1
  1538. static char rcsid[] = "$Header: /user2/mendel/lfs/src/cmds/mklfs/RCS/mklfs.c,v 1.1 90/05/31 15:51:23 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  1539. d145 1
  1540. d162 2
  1541. d254 12
  1542. a312 3
  1543.     if (maxCacheBlocksCleaned < 0) {
  1544.     maxCacheBlocksCleaned = 2*segmentSize/blockSize;
  1545.     }
  1546. d386 1
  1547. a386 1
  1548.     superBlockPtr->hdr.checkpointInterval = 60;
  1549. d662 3
  1550. a664 3
  1551.      * number get any smaller than the size of the file cache and
  1552.      * the segments being cleaned. Never let this number get below
  1553.      * five.
  1554. d666 4
  1555. a669 4
  1556.     usagePtr->minNumClean = (FS_BLOCK_SIZE * 
  1557.         (maxNumCacheBlocks + maxCacheBlocksCleaned))/segmentSize;
  1558.     if (usagePtr->minNumClean < 5) {
  1559.     usagePtr->minNumClean = 5;
  1560. d680 1
  1561. a680 1
  1562.         (usagePtr->minNumClean+5)*(segmentSize/blockSize)) {
  1563. d682 1
  1564. a682 1
  1565.         (usagePtr->minNumClean+5)*(segmentSize/blockSize);
  1566. d689 2
  1567. a690 1
  1568.      * until already clean. Must be bigger than cache.
  1569. d692 1
  1570. a692 1
  1571.     usagePtr->numSegsToClean = 2*usagePtr->minNumClean;
  1572. d696 1
  1573. a696 1
  1574.                         usagePtr->minNumClean - 5;
  1575. @
  1576.